/*************************************************************************************************
# Copyright (C), 20xx-20xx, xxx. Co., Ltd.
# File Name :		main.c
# Author : Chenxq		Version : V2.0		Date : 2019.01.24
# Description :
#	Main loop
# Others :
#	None
# Function List :
#	main
# History :
#	1.	Author : decorn		Version : V1.0		Date : 2017-08-10
#		Modification: Create
#	2.  Author : chenxq		Version : V2.0		Date : 2019-01-20
#		Modification: update
#************************************************************************************************/

/* Includes ------------------------------------------------------------------*/

#define FID_MAIN

#include "main.h"
#include "hmi_info.h"
#include "stm32f0xx.h"

bool_t   b8_uart_reflag;  //接收UART空闲状态位
bool_t   b8_uart_txflag;  //发送UART空闲状态位
bool_t   b8_flash_writeflag;  //FLASH 写操作标志位
uint8_t  u8_uart_fuction;      //串口通讯功能码

uint16_t  u16_McuACheckSMStep = 0u;  //输出自检测试计数
//uint8_t  u8_led_flash;   //led闪烁
ram_block_t	g_st_ram1;
ram_block_t	g_st_ram2;

//exch_com_run_dat_t  g_spi_ram3;

//uint8_t UART1_TXBUFFER[83];
//uint8_t UART1_RXBUFFER[83];

/*************************************************************************************************
# Function : main
# Descriptions :
#	Main function
# Input :
#	None
# Output :
#	None
# Return :
#	None
# Others :
#	None
# History :
#	1. Author : decorn		  Version : V1.0	  Date : 2017-08-10
# Modification: Create
#	2. 
#---------------------------------------------------------*/


void USART1_IRQHandler(void) //接收中断入口程序
{
	 if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
    {
			 USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除空闲中断
			 DMA_Cmd(DMA1_Channel5,DISABLE);     // 先关掉DMA通道
			 DMA_ClearFlag( DMA1_IT_GL5 );
			 //DMA_GetCurrDataCounter(DMA1_Channel5);
			 hmi_get_rx_dat(&UART1_RXBUFFER[0]); //接收处理程序
			 DMA_SetCurrDataCounter(DMA1_Channel5,UART_MAXLENGTH); // 设置需要接收的长度
			 DMA_Cmd(DMA1_Channel5,ENABLE); 
		}
}
void DMA1_Channel4_5_IRQHandler(void)  //UART_DMA中断入口程序
{  
         /*判断DMA传输完成中断*/
         if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET)                        
         { //数据发送完成，将命令清0
					 DMA_ClearITPendingBit(DMA1_IT_TC4);
					 b8_uart_txflag=BTRUE;
					 soft_dly_us(1000u);
					 UART_TX_DISABLE();
         }               
}
int main(void)
{
	uint16_t	u16_di_dat = 0u;   //DI数据初始化
	uint16_t	u16_do_dat = 0u;   //DO数据初始化
	uint8_t		u8_mcu_addr	= 0u;  //MCU地址初始化
	uint16_t	u16_idx		= 0u;
	uint8_t		*u8p_tmp1	= (uint8_t *)&g_st_ram1;  //强制转化为8位无符号数据类型
	uint8_t		*u8p_tmp2	= (uint8_t *)&g_st_ram2;
	bool_t		b8_tmp_master	= BFALSE; //MCU主从初始化为从MCU
	uint32_t	u32_RAM[5u] = {0u};
	uint16_t  u16_sm_step = 0u;
	
	/* Initialize double RAM data */
	if(DRAM_MAX_SIZE < sizeof(ram_block_t))
	{
		while(1)
		{
			;
		}
	}
	else
	{
		;
	}
	u8p_tmp1	= (uint8_t *)&g_st_ram1;
	u8p_tmp2	= (uint8_t *)&g_st_ram2;
	for(u16_idx = 0u; u16_idx < sizeof(ram_block_t); u16_idx ++)
	{
		*u8p_tmp1 = 0u;
		*u8p_tmp2 = 0u;
		u8p_tmp1 ++;
		u8p_tmp2 ++;
	}//RAM1/RAM2 ram_block_t初始化
	
	
	/* Initialize device */
	led_port_init();//指示灯初始化
	//bsp_Led_state(0x04);  //测试
	u8_mcu_addr = get_mcu_addr();//获取当前MCU地址
  g_st_ram1.run_display_data.instrument_hmi.u8_mcu_addr = u8_mcu_addr;//备份MCU地址
	g_st_ram2.run_display_data.instrument_hmi.u8_mcu_addr = u8_mcu_addr;//备份MCU地址

	if(u8_mcu_addr == ADDR_MCU_B)
	{
		/* MCU B */
		b8_tmp_master = BTRUE; //MCUB为主mcu
	}
	else
	{
		/* MCU A */
		b8_tmp_master = BFALSE;// MCUA为从MCU
	}
//	u16_RAM[0] = sizeof(uint8_t);   // 1  sizeof(exch_com_run_dat_t);
//	u16_RAM[1] = sizeof(uint16_t);  // 2
//	u16_RAM[2] = sizeof(uint32_t);  // 4
//	u16_RAM[3] = sizeof(bool_t);    // 1
	
		for(uint8_t u8_idx1 = 0u; u8_idx1<6u; u8_idx1++)  //初始化
	{
		 g_st_ram1.run_auxiliary_data.b8_led_flashflag[u8_idx1]=BFALSE ; //指示灯闪烁标志
		 g_st_ram2.run_auxiliary_data.b8_led_flashflag[u8_idx1]=BFALSE ; 
	}

	 dre_init(b8_tmp_master);//主从SPI的初始化
	 adc_init();//ADC初始化
	 mio_init();//I/O口初始化
	 wd_init();//看门狗引脚初始化
	 FlashCrc32_Init();
	 comm_tim_init();//公共定时器初始化：用于延时，滤波，定时
   USART1_Init(38400u); //串口初始化
	 USART1TX_DMA_Init();	//串口发送DMA初始化
	 USART1RX_DMA_Init(); //串口接收DMA初始化
	 USART1_DMA_RECEIVE(83u); //串口接收打开
	 diag_mcu_init(RUN_MODE, MCU_FAULT_TOL_NUM, &wd_clr);//MCU诊断初始化
	 diag_mcu_set_sfr_fun(&diag_sfr_rcc, &diag_sfr_syscfg, &diag_sfr_exti);
	 prg_init_val();//先初始化，再从flash中读出用户数据分别存入ram1和ram2
	 hmi_init_val();//诊断数据的初始化，主要是过压欠压诊断
	g_st_ram1.run_auxiliary_data.u16_sys_cnt = 0u;
	g_st_ram1.run_auxiliary_data.u16_sys_tim_old = comm_tim_get_currt_cnt();
	g_st_ram2.run_auxiliary_data.u16_sys_cnt = 0u;
	g_st_ram2.run_auxiliary_data.u16_sys_tim_old = g_st_ram1.run_auxiliary_data.u16_sys_tim_old ;
	while (1)
	{
		(void)diag_mcu_cycle(0u, 1u);//MCU自检，重要，必须放，不要动
		 dre_safe_poll(1u, 2u);//主从单片机进行SPI数据交互
  	 mio_get_di(3u, 3u, &u16_di_dat);//获取所有的DI状态，放到u16_di_dat
  	 prg_run_logic(6u, 4u, &u16_di_dat, &u16_do_dat);//解析用户逻辑，后面重点修改部分
		 led_control(10u, 5u); //LED控制
  	 mio_set_do(15u, 6u, u16_do_dat, g_st_ram1.run_display_data.instrument_hmi.u8_mcu_addr);//设置DO输出，给定DO值，Do还没输出
  	 mio_cyc_run(21u, 7u);	//DI/DO通道诊断，Do开始输出
  	 hmi_cycle_update(28u, 8u);//串口处理程序
  	 double_RAM_compare(36u, 9u);//RAM比较及数据比对
  	 diag_sequence_logic(45u); /* 诊断逻辑序列 wd_clr(); 45 */	
	}
}


static void double_RAM_compare(const uint8_t u8lc_init_val, const uint8_t u8lc_incr_val)//双RAM的比较
{
	uint16_t	u16_idx	= 0u;
	bool_t		b8_err	= BFALSE;
	bool_t		b8_fault_flg	= BFALSE;
	uint8_t   u8_fault[12];    //加入内部故障调试程序用。
	uint8_t   u8_fault_idx =0;
	
	uint8_t		*u8p_tmp1	= (uint8_t *)&g_st_ram1;
	uint8_t		*u8p_tmp2	= (uint8_t *)&g_st_ram2;
	
	diag_rcd_run_logic(u8lc_init_val, u8lc_incr_val);
	if(g_st_ram1.config_parameter.u16_config_crc!=g_st_ram1.run_display_data.u16_config_crc)
	{
		g_st_ram1.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_CRAM; //置CRAM故障
		g_st_ram2.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_CRAM; //置CRAM故障
	}
	else
	{
		g_st_ram1.run_display_data.instrument_hmi.u8_dev_fault &= ~BF_DIAG1_CRAM; //清CRAM故障
		g_st_ram2.run_display_data.instrument_hmi.u8_dev_fault &= ~BF_DIAG1_CRAM; //清CRAM故障
		//led_set_red(BFALSE);
		//g_st_ram1.run_display_data.instrument_hmi.u16_led &= (uint16_t)~RED_LED_LIGHT; //红灯灭 指示
		//g_st_ram2.run_display_data.instrument_hmi.u16_led &= (uint16_t)~RED_LED_LIGHT; //红灯灭 指示
	}
	
	///*	 内部故障调试程序    实际应用时应注释掉
//	for (u8_fault_idx=0;u8_fault_idx<12;u8_fault_idx++)
//	{
//	 u8_fault[u8_fault_idx]= diag_get_fault_cnt(u8_fault_idx);
//	}
//	*/
	
////	b8_fault_flg = diag_get_fault_exec(); //调试时候注释掉，不然会报错
	/*若有故障，输出断开*/
	if (b8_fault_flg==BTRUE)
	{
		g_st_ram1.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_MCU; //置MCU故障
		g_st_ram2.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_MCU; //置MCU故障
	}
	else
	{
	  g_st_ram1.run_display_data.instrument_hmi.u8_dev_fault &= ~BF_DIAG1_MCU; //清mcu故障
		g_st_ram2.run_display_data.instrument_hmi.u8_dev_fault &= ~BF_DIAG1_MCU; //清mcu故障
	}
	for(u16_idx = 0u; u16_idx < sizeof(ram_block_t); u16_idx ++)
	{
		if(*u8p_tmp1 != *u8p_tmp2)
		{
			b8_err	= BTRUE;
		}
		else
		{
			;
		}
		u8p_tmp1 ++;
		u8p_tmp2 ++;
	}
	if (b8_err==BTRUE)
	{
		g_st_ram1.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_DRAM; //置双口RAM比较故障，只有断电重启才能消除
		g_st_ram2.run_display_data.instrument_hmi.u8_dev_fault |= BF_DIAG1_DRAM; //置双口RAM比较故障，只有断电重启才能消除
	}
	else
	{
	  ;
	}
	//g_st_ram1.run_auxiliary_data.u8_dev_fault = b8_err;
	//g_st_ram2.b8_dual_ram_err = b8_err;
}



